#pragma once
#include <map>
#include "IOCPNetworkConst.h"
#include "TimeQueue.h"
#include "LockPool.h"
#include "ReadWriteLock.h"
#include "HighResolutionTimer.h"
#include "Lock.h"
/**************************
*
* 目的:
* 实现 Windows平台下支持超时控制的,可复用的IOCP网络模型框架(包括发送超时,接收超时,会话超时).
* 实现速度限制.
* 允许同时有一个读操作(accept和recv)和一个写操作(connect和send).
* 不支持同时有多个异步的读操作或者写操作.
*
* 关于同步
* 由于同一时刻只有一种类型的操作,所以可以用读锁.所有涉及到影响另一种类型操作的函数都要用写锁.
* 如果不需要同时进行读和写操作,即任何时刻内只有一个 IO 操作在进行,那么就可以不用同步(add()函数 sync = false 可以关闭同步)
*
* 对调用者的要求
* 1. 必须等待所有异步操作完成后(成功,失败或取消)才能调用remove删除.
* 2. 对于一个套接同一时刻同一种类型操作只有一个.
*/



class IOCPNetwork
{
public:
	
	IOCPNetwork();

	~IOCPNetwork();

	/**
	 * 初始化线程
	 * 工作线程的个数,如果 threads = 0 则创建当前CPU数等同数量的线程数
	 */
	int init(unsigned int thread);

	//销毁
	int destory();

	

	//sockt库初始化窗口param  NO.1主动发送 NO.2被动发送
	static bool initializeWindowSocket(WORD, WORD);



	/*
	* 异步操作函数
	* 参数s: 套接字句柄.
	* 参数key: 调用回调函数时传递参数.
	* accept: 执行异步accept操作.根据MSDN的说明,必须满足 len >= (sizeof(sockaddr_in) + 16) * 2
	* recv: 接收数据.
	*
	* 返回值: 预定义常量中的一个.
	  NO.1 完成键
	  NO.2 套接字
	  NO.3 缓冲区
	  NO.4 数据长度
	  NO.5 会话超时时间
	  NO.6 回调方法
	  NO.7 参数
	*/
	int accept(iocpKey key, SOCKET sockNew, byte* buf, size_t len, size_t timeout, IOCPProcCallBack func, void* param);

	/*
	 sessionTimeo 超时时间
	 readSpeedLmt 读取速度
	 writeSpeedLmt 写入速度
	 sync 是否同步
	*/
	iocpKey add(SOCKET s, unsigned long sessionTimeo, unsigned long readSpeedLmt, unsigned long writeSpeedLmt, bool sync = false);

	iocpKey add(HANDLE f, unsigned long sessionTimeo, unsigned long readSpeedLmt, unsigned long writeSpeedLmt, bool sync = false);

	SOCKET getSockopt(iocpKey);

	/*移除 客户端完成端口*/
	int remove(void *clientSocket);

	// 刷新socket
	void refresh(void *clientSocket);


	//异步操作方法

	/*
	  NO.1 客户端socket
	  NO.2 客户端socket内存缓冲区
	  NO.3 客户端socket内存缓冲区长度
	  NO.4 会话超时时间
	  NO.5 请求对象回调方法
	  NO.6 参数（请求对象的实例）
	*/
	int receive(void * clientSocket, byte * clientSocketBuff, unsigned  long clientBuffLen, unsigned long timeout, IOCPProcCallBack callBack, void *param);

	//发送数据
	int sendContent(void * clientSocket, byte * clientSocketBuff, unsigned  long clientBuffLen, unsigned long timeout, IOCPProcCallBack callBack, void *param);

protected:

	iocpKey add(HANDLE h, unsigned long sessionTimeo, unsigned long readSpeedLmt, unsigned long writeSpeedLmt, bool isFile, bool sync);

	//超时接收定时器回调方法
	static void __stdcall delayTimeByReceive(void * param, unsigned char str);


	//超时发送定时器回调方法
	static void __stdcall delayTimeBySend(void * param, unsigned char str);

	//读超时定时器回调方法
	static void __stdcall readTimeoutProc(void * param, unsigned char str);

	//启动服务管道
	static unsigned int __stdcall serviceCallBack(void * param);

	
	

private:

	//关闭复制
	IOCPNetwork(const IOCPNetwork &);

	IOCPNetwork & operator = (const IOCPNetwork &);

protected:

	//重叠结构的定义
	struct IOCPOverlappingStructure
	{
		//重叠
		OVERLAPPED ovp;

		//缓冲
		unsigned char * buffer;

		//数据长度
		unsigned int length;

		//实际长度 (实际传递给recv 函数的长度,由于速度限制的原因,可能小于length)
		unsigned int realLength;

		//管道（回调函数）
		IOCPProcCallBack proc;

		//额外的回调参数
		void * param;

		//超时定时器
		TimeQueue::timer_t timer;

		//超时时间
		unsigned int timeout;
		
		//速度限制
		unsigned long speedLimit;

		//最近完成发送的时间
		unsigned long lastCompleteTime;

		//共发送了多少数据
		unsigned long sendDataNUmber;

		//状态（输入输出完成端口状态）
		int status;
	};

	//IOCP 上下文结构
	struct IOCPContext
	{
		// 事件句柄 （可能 是 CreatEventc，或者是Socket创建的）
		HANDLE handler;

		// 读缓冲
		IOCPOverlappingStructure readBuff;

		// 写缓冲
		IOCPOverlappingStructure writeBuff;

		// 同步读写锁
		ReadWriteLock * rwLock;

		// IOCP套接字状态，读写保护
		int status;

		// 开始时间
		__int64 startTime;
		
		// 会话超时毫秒
		unsigned long sessionTimeout;

		// 句柄类型 文件或者套接字
		int type;

		//类实例指针内部使用
		IOCPNetwork * iocpNetwork;
	};

	//连接map
	typedef std::map<HANDLE, IOCPContext*> connectMap;


	//定时器队列
	TimeQueue timeQueue;

	/*输入输出完成端口句柄*/
	HANDLE iopcHandle;

	//同步对象池
	LockPool<ReadWriteLock> lockPool;


	//最后一个错误代号
	DWORD lastErrorCode;

	//工作线程id数组
	uintptr_t * threadIdArray;

	//工作线程数
	int thread;

	//是否已经初始化
	bool isAlreadyInitialize;

	//高精度计时器
	HighResolutionTimer hrt;

	//普通锁
	Lock lockObj;

	//存放连接map
	connectMap connectStock;

	//初始化上下文
	IOCPContext * allocContnext();

	//会话是否超时
	bool sessionTimeout(IOCPContext *);


	/*iocp完成时，回调给上层时处理一些事务*/
	void onFinishedByIO(IOCPContext  *iocpContnext, IOCPOverlappingStructure *olp, bool result, int transfer);
	
	//清理重叠结构
	
	void cleanOlp(IOCPOverlappingStructure * olp);

	/*
	 实际接收了多少
	*/
	int realReceive(IOCPContext *iocp);

	// 实际发送
	size_t realSend(IOCPContext * iocpContext);
};

